import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.util.Date;
import java.util.List;

import javax.imageio.stream.FileImageOutputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import com.blade.mvc.multipart.FileItem;

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLRelation;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import word.WordToHtmlConverter;
import word.DocxToHtmlConverter;


/**
 * 利用 POI 解析 .doc, .docx 并转换为 html
 */
public class WordParser {

  /**
   * 解析 word 2003 版后缀名为 .doc 的 word 文件
   * @return 
   * @throws IOException
   * @throws ParserConfigurationException
   * @throws TransformerException
   */
  public String parseDoc(byte[] bytes) throws IOException, TransformerException, ParserConfigurationException {
    InputStream is = new ByteArrayInputStream(bytes);
    // File file = new File("/data/home/shu/workspace/demos/文档1.doc");
    // 构建 word 文档，老版本的 word2003 .doc 文件, 需要引入 poi-scratchpad
    HWPFDocument doc = new HWPFDocument(is);
    // word to html 解析器
    WordToHtmlConverter htmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
    htmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> { 
      /*
        这里是将图片转换为 base64 形式，实际推荐保存文件，然后返回图片 url
      */
      // new Date().getTime();
      String saveName = Math.floor(Math.random()*10) + new Date().getTime() + suggestedName;
      String savePath = "E:/java_pros/ParseWord/build/classes/java/main/static/" + saveName;
      FileImageOutputStream fios = null;
      try {
        fios = new FileImageOutputStream(new File(savePath));
        fios.write(content);
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        try {
          if (fios != null) {
            fios.close();
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      // 对字节数组进行Base64编码，得到Base64编码的字符串
      // Base64.Encoder encoder = Base64.getEncoder();
      // String base64Str = encoder.encodeToString(content);
      // // 带图片的word，则将图片转为base64编码，保存在一个页面中
      // StringBuilder sb = (new StringBuilder("data:" + pictureType.getMime() + ";base64,").append(base64Str));
      return "http://127.0.0.1:9000/static/" + saveName;
    });
    htmlConverter.processDocument(doc); // 解析 word 文档
    // 获取解析后的 html 文档
    Document htmlDocument = htmlConverter.getDocument();
    Node bodyNode = htmlDocument.getElementsByTagName("body").item(0);
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    DOMSource domSource = new DOMSource(bodyNode);
    StreamResult streamResult = new StreamResult(os);

    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer serializer = factory.newTransformer();
    serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
    serializer.setOutputProperty(OutputKeys.INDENT, "no");
    serializer.setOutputProperty(OutputKeys.METHOD, "html");
    serializer.setOutputProperty(OutputKeys.VERSION, "HTML");

    serializer.transform(domSource, streamResult);

    os.close();
    return new String(os.toByteArray(), "utf-8");
  }

  public String parseDocx(byte[] bytes) throws Exception {
    InputStream is = new ByteArrayInputStream(bytes);
    XWPFDocument doc = new XWPFDocument(is);

    // docx -> html 转换器
    DocxToHtmlConverter converter = new DocxToHtmlConverter();
    // 设置图片管理
    converter.setPicturesManager((content, pictureType, fileName, suggestedName, widthInches, heightInches) -> {  
      String[] fileinfo = fileName.split("\\.");
      // new Date().getTime();
      String saveName = fileinfo[0] + new Date().getTime() + "." + fileinfo[1];
      String savePath = "E:/java_pros/ParseWord/build/classes/java/main/static/" + saveName;
      FileImageOutputStream fios = null;
      try {
        fios = new FileImageOutputStream(new File(savePath));
        fios.write(content);
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        try {
          if (fios != null) {
            fios.close();
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      
      /*
        这里是将图片转换为 base64 形式，实际推荐保存文件，然后返回图片 url
      */
      // 对字节数组进行Base64编码，得到Base64编码的字符串
      // Base64.Encoder encoder = Base64.getEncoder();
      // String base64Str = encoder.encodeToString(content);
      // // 带图片的word，则将图片转为base64编码，保存在一个页面中
      // StringBuilder sb = (new StringBuilder("data:" + pictureType.getMime() + ";base64,").append(base64Str));
      
      return "http://127.0.0.1:9000/static/" + saveName;
    });
    converter.processDocument(doc); // 解析 docx 文档
    return converter.getHtmlString();
  }
}
